/*
 * Copyright (c) 2009
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.dcarew.hudson;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;

import org.dcarew.hudson.utils.LabelContributionItem;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuCreator;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.action.StatusLineManager;
import org.eclipse.jface.preference.PreferenceDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.ui.IStartup;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.browser.IWebBrowser;
import org.eclipse.ui.browser.IWorkbenchBrowserSupport;
import org.eclipse.ui.dialogs.PreferencesUtil;
import org.eclipse.ui.internal.WorkbenchWindow;

/**
 * The IStartup item for the Halo status project. This is run an Eclipse startup and adds our
 * contribution item to the status line.
 * 
 * @author Devon Carew
 */
public class HudsonStartup
	implements IStartup
{
	private static HudsonStartup hudsonStartup;
	
	
	private LabelContributionItem 	label;
	
	private boolean 				hasError;
	
	private String					currentView;
	
	private List					views;
	
	
	public HudsonStartup()
	{
		hudsonStartup = this;
	}
	
	/**
	 * Called by the workspace after general statup.
	 */
	public void earlyStartup()
	{
		PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
		    public void run() {
		    	addStatusLineContribution();
		    }
		});
	}
	
	public static HudsonStartup getStartup()
	{
		return hudsonStartup;
	}
	
	public void update(boolean allOK, boolean hasRunning, String text, String tooltip,
		String currentView, List views)
	{
		setHudsonStatus(label, allOK, hasRunning, text, tooltip, currentView, views);
	}
	
	public void updateError(String text, String tooltip)
	{
		setHudsonStatusError(label, text, tooltip);
	}
	
	/**
	 * Adds the cruise control status line contrubution. This must be called from the display thread.
	 */
	private void addStatusLineContribution()
	{
		IWorkbenchWindow[] windows = PlatformUI.getWorkbench().getWorkbenchWindows();
		
		if (windows.length < 1)
			throw new IllegalStateException("should be at least one workbench window");
		
		WorkbenchWindow window = (WorkbenchWindow)windows[0];
		
		final StatusLineManager statusLineManager = window.getStatusLineManager();
		
		label = new LabelContributionItem(HudsonPlugin.PLUGIN_ID + ".statusContribution", new LabelMenuCreator());
		label.setDoubleClickAction(new Action("doubleClick") {
			public void run() {
				handleDoubleClick();
			}
		});
		
		statusLineManager.add(new Separator("hudson"));
		statusLineManager.appendToGroup("hudson", label);
		
    statusLineManager.update(true);
	}
	
	private void setCurrentView(String name)
	{
		HudsonPlugin.setHudsonView(name);
		
		HudsonUpdateJob.refresh();
	}
	
	private void handleDoubleClick()
	{
		// If no URL is set or there's a communications error, open the
		// preference page. Otherwise, open a browser.
		
		String url = HudsonPlugin.getBaseURL();
		
		if (hasError || url == null || url.length() == 0)
		{
			PreferenceDialog dialog = PreferencesUtil.createPreferenceDialogOn(
				Display.getDefault().getActiveShell(), HudsonPreferencePage.PAGE_ID, null, null);
			
			if (dialog != null)
				dialog.open();
		} 
		else
		{
			IWorkbenchBrowserSupport browserSupport = PlatformUI.getWorkbench().getBrowserSupport();
			
			try
			{
				if (browserSupport != null)
				{
					IWebBrowser browser = browserSupport.createBrowser(
						IWorkbenchBrowserSupport.NAVIGATION_BAR, "HudsonBrowser", null, null);
					
					if (browser != null)
					{
						browser.openURL(new URL(url));
						
						return;
					}
				}
			}
			catch (PartInitException exception)
			{
				HudsonPlugin.log(exception);
			}
			catch (MalformedURLException exception)
			{
				HudsonPlugin.log(exception);
			}
		}
	}

	private void setHudsonStatus(
		final LabelContributionItem label,
		final boolean allOK,
		final boolean hasRunning,
		final String status,
		final String tooltip,
		String currentView,
		List views)
	{
		this.currentView = currentView;
		this.views = views;
		
		hasError = false;
		
		if (label == null)
			return;
		
		Display.getDefault().asyncExec(new Runnable() {
			public void run() {
				if (allOK)
				{
					if (hasRunning)
						label.setImage(HudsonPlugin.getImage("resources/icons/hudsonok_run.gif"));
					else
						label.setImage(HudsonPlugin.getImage("resources/icons/hudsonok.gif"));
				}
				else
				{
					if (hasRunning)
						label.setImage(HudsonPlugin.getImage("resources/icons/hudsonfail_run.gif"));
					else
						label.setImage(HudsonPlugin.getImage("resources/icons/hudsonfail.gif"));
				}
				
				label.setText(status);
				label.setTooltip(tooltip);
			}
		});
	}
	
	private void setHudsonStatusError(
		final LabelContributionItem label,
		final String status,
		final String tooltip)
	{
		hasError = true;
		
		if (label == null)
			return;
		
		Display.getDefault().asyncExec(new Runnable() {
			public void run() {
				label.setImage(HudsonPlugin.getImage("resources/icons/hudsonfail2.gif"));
				label.setText("Error");
				label.setTooltip(tooltip);
			}
		});
	}
	
	class LabelMenuCreator
		implements IMenuCreator
	{
		public Menu getMenu(Control parent)
		{
			Menu menu = new Menu(parent);
			
			MenuItem item = new MenuItem(menu, SWT.NONE);
			item.setText("Open Hudson Dashboard");
			item.addSelectionListener(new SelectionAdapter() {
				public void widgetSelected(SelectionEvent event) {
					handleDoubleClick();
				}
			});
			
			item = new MenuItem(menu, SWT.NONE);
			item.setText("Preferences...");
			item.addSelectionListener(new SelectionAdapter() {
				public void widgetSelected(SelectionEvent event) {
					PreferenceDialog dialog = PreferencesUtil.createPreferenceDialogOn(
						Display.getDefault().getActiveShell(), HudsonPreferencePage.PAGE_ID, null, null);
					
					if (dialog != null)
						dialog.open();
				}
			});
			
			new MenuItem(menu, SWT.SEPARATOR);
			
			// Add the Hudson views.
			if (views != null)
			{
				for (int i = 0; i < views.size(); i++)
				{
					final String name = (String)views.get(i);
					
					item = new MenuItem(menu, SWT.CHECK);
					item.setText(name);
					item.addSelectionListener(new SelectionAdapter() {
						public void widgetSelected(SelectionEvent event) {
							setCurrentView(name);
						}
					});
					
					if (name.equals(currentView))
					{
						item.setSelection(true);
					}
				}
			}
			
			return menu;
		}
		
		public Menu getMenu(Menu parent)
		{
			return null;
		}
		
		public void dispose()
		{
			
		}
	}

}
